/**
 * @file   AbstractNode.h
 * @author Djuro Drljaca (djurodrljaca@gmail.com)
 * @date   2014-04-27
 * @brief  Base class for a DON node.
 *
 * Copyright 2014  Djuro Drljaca (djurodrljaca@gmail.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DON_CORE_NODE_DATAOBJECTMODEL_H
#define DON_CORE_NODE_DATAOBJECTMODEL_H

#include <DON/Core/Node/CommunicationMode.h>

namespace DON
{
namespace Core
{
namespace Packet
{

class AbstractPacket;
class GenericPacket;

}

namespace Node
{

/**
 * @brief The AbstractNode class
 */
class LIBDONQT4CORESHARED_EXPORT AbstractNode
{
public:
    /**
     * @brief Constructor
     */
    AbstractNode();

    /**
     * @brief Destructor
     */
    virtual ~AbstractNode();

    /**
     * @brief Checks if this nodes parameters are valid
     * @retval true This nodes parameters are valid
     * @retval false This nodes parameters are not valid
     */
    virtual bool isValid() const = 0;

    /**
     * @brief Get network address
     * @return Network address
     */
    quint16 getNetworkAddress() const;

    /**
     * @brief Get number of network addresses that are reseved by this node
     * @return Number of reserved network addresses
     */
    quint16 getNetworkAddressCount() const;

    /**
     * @brief Set network address
     * @param networkAddress New network address
     *
     * @note This method also sets the number of reserved network addresses (address count) to 1.
     */
    void setNetworkAddress(const quint16 networkAddress);

    /**
     * @brief Set network address range
     * @param networkAddress Address of this node
     * @param networkAddressCount Number of addresses reserved by this node
     */
    void setNetworkAddressRange(const quint16 networkAddress, const quint16 networkAddressCount);

    /**
     * @brief Get name
     * @return Node's name
     */
    QString getName() const;

    /**
     * @brief Set name
     * @param name Node's new name
     */
    void setName(const QString &name);

    /**
     * @brief Get type
     * @return Node's type
     *
     * The node type is a short description of the purpose of the node.
     * Here are a few examples for types:
     * - "RS232 DON Server"
     * - "TCP DON Server"
     * - "Temp. sensor"
     * - "Humid. sensor"
     * - "Light switch"
     * - "Power meter"
     */
    QString getType() const;

    /**
     * @brief Set type
     * @param type Node's new type
     */
    void setType(const QString &type);

    /**
     * @brief Get communication mode
     * @return Node's communication type
     */
    CommunicationMode getCommunicationMode() const;

    /**
     * @brief Set communication mode
     * @param communicationMode
     */
    void setCommunicationMode(const CommunicationMode communicationMode);

    /**
     * @brief Get maximum payload length
     * @return Node's maximum payload length
     */
    quint16 getMaxPayloadLength() const;

    /**
     * @brief Set maximum payload length
     * @param maxPayloadLength Node's new maximum payload length
     */
    void setMaxPayloadLength(const quint16 maxPayloadLength);

    /**
     * @brief Get next sequence number
     * @return Next sequence number
     *
     * @note Default implementation just returns a value that is auto-incremented
     */
    virtual quint16 getNextSequence();

    /**
     * @brief Send packet
     * @param packet Packet to send
     * @retval true Success
     * @retval false Error
     */
    bool sendPacket(const Packet::AbstractPacket &packet);

protected:
    /**
     * @brief Handle received packet
     * @param receivedPacket Received packet
     *
     * @note Default implementation just discards the packet
     */
    virtual void handleReceivedPacket(const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Add received data to the receive buffer
     * @param receivedData Received data
     */
    void addReceivedData(const QByteArray &receivedData);

    /**
     * @brief Process received data
     */
    virtual void processReceivedData();

    /**
     * @brief Send data
     * @param data Data to be sent
     * @retval true Success
     * @retval false Error
     *
     * When a node sends a packet it first tries to get a binary representation of the packet and
     * if it is successful then this method is called with the binary representation of the packet.
     * A derived class must then send the data through it's communication channel.
     *
     * Default implementation just discards the data.
     *
     * @note A derived class must reimplement this method to be able to send packets.
     */
    virtual bool sendData(const QByteArray &data);

private:
    AbstractNode(const AbstractNode &other);
    AbstractNode & operator=(const AbstractNode &other);

    class Private;
    Private *d;
};

}
}
}

#endif // DON_CORE_NODE_DATAOBJECTMODEL_H
